﻿#include "rec_write.h"
#include "media_frame_hd.h"

const uint32_t  DEF_FRM_DIFFSIZE = (DEF_RECORD_SIZE - STFS_REC_DATA_OFFSET)/STFS_MAX_RECIDX_NUM;
CRecordWriter::CRecordWriter(int channel)
{

	m_curPos = 0;
	m_endTime = 0;
	m_idxDiffTm = STFS_1SEC_MS;
	m_idxDiffComSize = (SIZE_MB(64)- STFS_REC_DATA_OFFSET)/STFS_MAX_RECIDX_NUM/3;
	memset(&m_curSeg,0,REC_SEG_LEN);
	memset(&m_recIdx,0,REC_INDEX_LEN);
	m_fileHeadOffset= 0;
	m_channel = channel;
	m_lastFrmNO = 0;
	m_fileHead.fileSpace = SIZE_MB(64);
	
}

CRecordWriter::~CRecordWriter()
{
	if(m_pFile)
	{
		delete m_pFile;
	}
	m_vecSeg.clear();
}

int CRecordWriter::Open(const char * dev, uint32_t fileIndex, uint32_t fileSize,int64_t startTime,PSTFS_RECINFO_EXTERN pExternInfo)
{
	int ret  = 0;

	if(m_pFile != NULL && m_pFile->IsOpened())
	{
#ifdef _CBS_DEBUG_
		TRACE("CH %02d fileIndex %d - %d - %d File is opened.curpos %d.\n",channel,m_fileHead.indexNO,m_curSeg.segNO,m_recIdx.NO,m_curPos);
#endif
		m_endTime   = startTime;
		m_lastFrmNO = 0;
		return ERR_FILE_OPENED;
	}

#if 0
	CSCSI_Dev* pDev = g_scsiDevFac.CreateScsiDev(dev);
	if( NULL == pDev)
	{
		TRACE_ERR("No device %s .\n", dev);
		return ERR_NO_DEVICE;
	}
	uint64_t fileLBA = g_diskInfoSet.GetAssignFileLBA(dev,fileIndex);
	ret = m_pFile->Open(pDev,fileLBA,fileSize,SCSI_RDWR);
#else
	ret = OpenFile(dev,fileIndex,fileSize);
#endif

	if(ret < 0)
	{
		TRACE("Open fileIndex fail %d ret %d \n",fileIndex,ret);
		m_pFile->Close();
		return ret;
	}

	if(NULL != pExternInfo)
	{	//扩展信息
		m_fileHead.recordSN    = pExternInfo->recordSN ;
		strcpy(m_fileHead.softVersion,pExternInfo->softVersion);
	}

	InitHeadInfo(fileSize,fileIndex,startTime,pExternInfo);
	InitFifoBuf();
	m_frmIdx.Reset();
	ClearIndexArea();
	WriteRecHeadInfo();

	m_curPos  = m_fileHead.dataOffset;

	
	//if(m_bRawDev)
	{
		Start_FlushData(m_curPos);
	}
	m_endTime   = startTime;
	m_lastFrmNO = 0;
	TRACE("CH%02d Open file index %d OK fileSize %d LBA %lld.diffComsize %d.\n",
		m_channel,fileIndex,fileSize,m_pFile->get_lba_start(),m_idxDiffComSize);
	PrintTimeMs(startTime,0,"open record start");

	return 0;
}


int CRecordWriter::OpenRepairFile(REC_FILE_INFO & recInfo,uint32_t fileLen,int64_t startTime)
{
	int ret  = 0;
    int maxIdx =0;
    uint32_t i;

    STFS_REC_IDX * pRecIdx  = NULL;

	char * dev = 0; //g_diskInfoSet.GetDiskInfo(recInfo.diskIndex)->diskName;

	ret = OpenFile(dev,recInfo.indexNo,fileLen);
	
	m_frmIdx.Open(STFS_REC_DATA_OFFSET,STFS_REC_IDX_OFFSET,512);

	uchar_t * pBuf = m_frmIdx.GetBufAddr();

	//读取
	m_pFile->Seek(0,SCSI_SEEK_SET);
	ret = m_pFile->Read(pBuf,STFS_REC_DATA_OFFSET);
	if(ret < 0)
	{
		goto ERR_OUT;
	}
	
	//1. 处理文件头部
	memcpy(&m_fileHead,pBuf,sizeof(STFS_REC_FILEHEAD));
	m_fileHead.fileSpace   = fileLen;
	m_fileHead.channel     = m_channel;
	m_fileHead.writeStatus = STFS_REC_WT_APPEND;
	//2.录像段
	m_vecSeg.clear();
	for(uint32_t i = 0; i < STFS_MAX_SEG_NUM ; i++)
	{
		STFS_REC_SEG* pRecSeg = (STFS_REC_SEG *)(pBuf + i * REC_SEG_LEN + STFS_REC_SEG_OFFSET);
		if(STFS_REC_SEG_SIG == pRecSeg->magic)
		{
			m_vecSeg.push_back(*pRecSeg);
			continue;
		}
	}
	memset(&m_curSeg,0,REC_SEG_LEN);
	m_curSeg.segNO      = recInfo.segIndex + 1;
	m_curSeg.tmStart	= recInfo.tmStart;
	m_curSeg.magic      = STFS_REC_SEG_SIG;

	//3.索引区
	pRecIdx = (STFS_REC_IDX *)(pBuf + STFS_REC_IDX_OFFSET);
	for(i = 0; i < STFS_MAX_RECIDX_NUM; i++)
	{
		if(pRecIdx[i].magic     == 0 &&
			pRecIdx[i].offset   == 0)
		{
			break;
		}
		maxIdx++;
	}

	m_frmIdx.InitStartPos(maxIdx * sizeof(STFS_REC_IDX),0);

	//刷新头文件信息进去
  	m_curSeg.data_endpos = m_curSeg.data_start = m_curPos =  m_fileHead.fileLen;//recInfo.endOffset;
	m_vecSeg.push_back(m_curSeg);

	if(m_curPos == 0)
	{
		return ERR_DATA_OVER_FILE;
	}
	if(!m_pfifo_buf->IsOpen())
	{
		ret = m_pfifo_buf->open(FIFO_SIZE);
	}

	WriteRecHeadInfo();
	InitFifoBuf();
	Start_FlushData(m_curPos);

	m_endTime          = startTime;
	TRACE("CH%02d OpenRepairFile index %d OK last offset %d\n",m_fileHead.channel,m_fileHead.indexNO,m_fileHead.fileLen);
	return 0;
ERR_OUT:
	m_pFile->Close();
	return ret;
}

int CRecordWriter::Close()
{
	int ret = 0;

	ret = CRecWriteBase::Close();

	return ret;
}

//写入单帧数据
int CRecordWriter::WriteFrame(uchar_t * frameBuf, uint32_t dataSize)
{
	int		ret        = 0;	//返回值
	m_frmTool.Init(frameBuf);
	uint32_t destOffset = m_curPos + dataSize;

	//检查文件是否超界
	if(destOffset > m_fileHead.fileSpace)
	{
		TRACE_ERR("CH%02d Data is over file.dataSize %d curPos %d destOffset %d file size %d .\n",
			m_fileHead.channel,dataSize,m_curPos,destOffset,m_fileHead.fileSpace);
		return ERR_DATA_OVER_FILE;
	}

	int frmType  = m_frmTool.GetFrameType();
	int64_t time = m_frmTool.GetFrameTime();
	bool bKeyFrm = m_frmTool.IsKeyFrame();
	uint32_t curNo = m_frmTool.GetFrameNo();
	int64_t dffTime = 0;
	//检查索引区是否已经满了
	if( m_recIdx.NO    >= STFS_MAX_RECIDX_NUM ||
		m_curSeg.segNO >= STFS_MAX_SEG_NUM)
	{
		TRACE_ERR("Over max index NUM or segment.curPos %d index %d.seg %d,\n",
				  m_curPos,m_recIdx.NO,m_curSeg.segNO);
		return ERR_SPACE_NOTENOUGH;
	}

	if( 0 == m_recIdx.NO )
	{
		if(!bKeyFrm)
		{
			return ERR_NOT_KEY_FRAME_1STVEDIO;
		}
	}

	if( bKeyFrm &&
		GetFreeSize() < SIZE_1MB)
	{
		ret = AnsureKeyFrameSpace();
		if( ret < 0)
		{   // 剩余的空间大小不够存储两个I之间完整的视频数据

			return ERR_FOR_SAVE_KEY_FRAME;
		}
	}


	//判断时间
	if( 0 != m_curSeg.tmStart)
	{
		//时间倒退
		if((time + 5*STFS_1SEC_MS) < m_endTime)
		{
			//时间跳变大于30秒，则进行切换文件
			PrintTimeMs(time,0,"Cur time");
			PrintTimeMs(m_endTime,0,"Record last time");
			TRACE_ERR("CH%02d index %d Time jumped. cur frm NO %d last NO %d\n",
				m_fileHead.channel,m_fileHead.indexNO,
				curNo,m_lastFrmNO);
			m_endTime = time;
			return ERR_TM_JUMP_BACK;

		}
		else
		{
			dffTime = ABS(time - m_endTime);
			if(dffTime > STFS_REC_TIME_JUMP)
			{//往前跳变

				PrintTimeMs(m_endTime,0,"last time");
				PrintTimeMs(time,0,"cur frame time");
				TRACE("CH %02d Tm jump forward. diff  %lldd ms",m_channel,dffTime);
				
				return ERR_TM_JUMP_FORWARD;;
			}
		}
	}


	if(IsContextCreateIdx(frmType,time))
	{
		CreateRecIndex(frmType,dataSize,time,m_curPos);
	}

	//录像段记录
	if(0 == m_curSeg.tmStart)
	{
	   m_curSeg.tmStart = time;
	   SetSegmentInfo(m_curSeg);
	}

	//写入数据,传入到FIFO缓冲，底层专门的线程去刷新数据
#if 1
	ret = WriteFIFO(frameBuf,dataSize);
#else
	if(m_bRawDev)
	{
		ret = WriteFIFO(frameBuf,dataSize);
	}
	else
	{

		ret = m_pFile->WriteCachePos(m_curPos,frameBuf,dataSize);
		uint32_t dataPos = m_pFile->get_cur_offset();
		if(dataPos <= m_curPos)
		{
			TRACE("Write data  fail. real dataPos %d. m_curPos %d\n",m_curPos,dataPos);
			return ERR_DATA_OVER_FILE;
		}
	}
#endif
	if(ret < 0)
	{
		TRACE_ERR("Write FIFO fail.size %d.ret %d\n",dataSize,ret);
		return ret;
	}

	m_curPos     += dataSize;
	m_fileHead.endTime = m_endTime     = time;
	m_lastFrmNO   = curNo;
	
//	m_vedioHeight = pFHead->video.VHeight;
//	m_vedioWidth  = pFHead->video.VWidth;  //记录最后一帧的宽高

	return dataSize;
}

//检测数据偏移是否正确
int CRecordWriter::IdentifyData(STFS_REC_IDX recIdx)
{
	int bufSize = SIZE_KB(500);
	unsigned char * tmpBuf = new unsigned char[bufSize];
	if(tmpBuf == NULL)
	{
		return ERR_PARAM;
	}
	int ret = m_pFile->ReadPos(recIdx.offset,tmpBuf,bufSize);
	if(ret < 0)
    {
        return 0;
    }
	int addoffset  = 0;
	bool bFound    = false;
	while ((addoffset + FRM_HEAD_LEN)< bufSize)
	{
		FsFrame_t * pHead = (FsFrame_t*)(tmpBuf + addoffset);
		if(pHead->frameTag  == FSFrameTag )
		{
			if(pHead->time     == recIdx.tmMS)
			{
				PrintTimeMs(recIdx.tmMS,0,"Rec idx time");
				bFound = true;
				recIdx.offset += addoffset;
				break;
			}
			PrintTimeMs(pHead->time,0,"Rec idx time");
			TRACE("Frame no %d len %d .\n",pHead->frameNo,pHead->dataLen);
		}
		addoffset++;
	}
	if(tmpBuf != NULL)
	{
		delete [] tmpBuf;
	}
	if(!bFound)
	{
		CROSS_ASSERT(false);
	}

	return 0;
}


//合并小段录像，避免碎片太多
void CRecordWriter::MergeRec(REC_FILE_INFO & recordInfo)
{
	int seg = m_vecSeg.size();
	if(seg > 0)
	{
		m_curSeg.type        = recordInfo.recordType;
		m_curSeg.tmStart     = m_vecSeg[seg - 1].tmStart;
		m_curSeg.idx_startNo = m_vecSeg[seg - 1].idx_startNo;
		m_curSeg.data_start  = m_vecSeg[seg - 1].data_start;
		recordInfo.segIndex  = m_curSeg.segNO  = m_vecSeg[seg - 1].segNO;
		recordInfo.length    = m_curPos - m_vecSeg[seg- 1 ].data_start;

		m_vecSeg.pop_back();
	}
}

int CRecordWriter::RepairFile(char*  diskName,uint32_t fileIndex,uint64_t fileLBA,uint32_t recSize,int64_t startTime, uint32_t& fileSize,int64_t & endTime)
{
	//打开文件对象
	if( NULL == diskName)
	{
		TRACE_ERR("Disk name is empty,\n");
		return ERR_NO_DEVICE;
	}

	uint32_t i = 0;
	int ret = 0;
	uint32_t offset = 0;
	uint32_t startOffset = 0, endOffset = 0;

	STFS_REC_IDX *pIdxBuf   = NULL;
	STFS_REC_IDX *plastIdx  = NULL;
	uchar_t		 * pBuf     = NULL;
	uchar_t		 * pDataBuf = NULL;
	char tmpPath[40] = {0};
	char filePath[60] = {0};

	int indexLen = (STFS_REC_DATA_OFFSET - STFS_REC_IDX_OFFSET)/REC_INDEX_LEN;
	int bufSize  = SIZE_2MB;
	bool bRaw = CSerialFileBase::IsRawDevice(diskName);
	uint32_t recFileSize = SIZE_MB(256);

#if 0
	uint32_t recSpace = g_diskInfoSet.GetRecFileSize();
	if(NULL == m_pFile)
	{
		m_pFile = g_serialFileFac.CreateSerialFile(diskName);
	}
	else
	{
		if(m_bRawDev != bRaw)
		{
			m_pFile = g_serialFileFac.CreateSerialFile(diskName);
		}
	}

	if(bRaw)
	{
		CSCSI_Dev* pDev = g_scsiDevFac.CreateScsiDev(diskName);
		if( NULL == pDev)
		{
			return ERR_NO_DEVICE;
		}

		ret = m_pFile->Open(pDev,fileLBA,recSpace,SCSI_RDWR);
	}
	else
	{
		GetFileDestPath(tmpPath,diskName);
#ifdef _WIN32
		strcat(tmpPath,"Record\\");
#else
		strcat(tmpPath,"Record/");
#endif
		if( -1 == access(tmpPath,0))
		{
			return ERR_NO_RECFILE;
		}
		sprintf(filePath,"%s%05d.asf",tmpPath,fileIndex);
		TRACE("Dest filePath %s .\n",filePath);
		
		ret = m_pFile->Open(filePath,fileLBA,fileSize,SCSI_RDWR);
	}
#endif
	m_frmIdx.Open(STFS_REC_DATA_OFFSET,STFS_REC_IDX_OFFSET,512);
	int secSize = m_pFile->get_sec_size();
	//多段录像
	//读取文件头信息
	pBuf = m_frmIdx.GetBufAddr();
	STFS_REC_FILEHEAD* pHead = (STFS_REC_FILEHEAD*)pBuf;
	ret = m_pFile->ReadPos(0,pBuf,STFS_REC_IDX_OFFSET);
	if(STFS_REC_IDX_OFFSET != ret)
	{
		TRACE_ERR("Read file head fail. ret %d.\n ",ret);
		return ret;
	}
	ret = DetectFileHead(pBuf,STFS_REC_IDX_OFFSET);
	if(ret < 0)
	{
		TRACE_ERR("Not a record file.\n");
		return ret;
	}
	//比较签名
	m_endTime      = pHead->startTime;
	pHead->fileLen = SIZE_MB(256); //g_diskInfoSet.GetRecFileSize();
	//判断文件是否为录像文件
	indexLen = pHead->dataOffset - pHead->idxOffset;			//;  m_dataOffset - m_idxOffset;
	if(indexLen > STFS_REC_DATA_OFFSET)
	{
		TRACE_ERR("Error data len %d.\n",indexLen);
		indexLen = STFS_REC_DATA_OFFSET - STFS_REC_IDX_OFFSET;
	}
	uint32_t maxNum    = (uint32_t)(indexLen/REC_INDEX_LEN);
	indexLen      = maxNum * REC_INDEX_LEN;
	int indexCnt  = 0;
	int lastIndex = 0,indexBak = 0;

 	pIdxBuf  = new STFS_REC_IDX[maxNum];
	//读取所有索引数据
	ret = m_pFile->ReadPos(pHead->idxOffset,(uchar_t*)pIdxBuf,indexLen);
	if(ret != indexLen)
	{
		TRACE("Read index buf fail.\n");
        if(pIdxBuf)
        {
            delete [] pIdxBuf;
        }
        return ret;
	}

	//读取索引段
	PSTFS_REC_SEG pReg = (PSTFS_REC_SEG)(pBuf + STFS_REC_SEG_OFFSET +m_fileHeadOffset);
	for (i = 0 ; i < STFS_MAX_SEG_NUM ; i++)
	{
		if(pReg[i].magic != STFS_REC_SEG_SIG)
		{
			break;
		}
		m_vecSeg.push_back(pReg[i]);
		if((startTime/1000 - pReg[i].tmEnd) > 0  || pReg[i].tmStart == startTime/1000 )
		{
			startOffset = pReg[i].data_start;
		//	TRACE("NO%02d CH%02d Start offset %d. Start Time",i,pHead->channel,startOffset);
		}
		//PrintTimeMs(pReg[i].tmStart,pReg[i].tmEnd,"Record seg");
	}

	//读取索引记录
	lastIndex = indexBak = 0;
	uint32_t startTmSec = (uint32_t)(startTime/STFS_1SEC_MS);
	for(i = 0 ; i < maxNum; i++)
	{
		if( STFS_REC_IDX_SIG != pIdxBuf[i].magic &&
			STFS_GPS_IDX_SIG  != pIdxBuf[i].magic)
		{
			if( IFrame!= pIdxBuf[i].frameType)
			{
				TRACE_ERR("Error data index %d.\n",i);
				lastIndex = i;
				break;
			}
			else
			{
				continue;
			}
		}

		if(STFS_GPS_IDX_SIG  == pIdxBuf[i].magic)
		{
			continue;
		}

		if( startOffset == 0 &&
			pIdxBuf[i].tmMS >= startTime)
		{
			startOffset = pIdxBuf[i].offset ;
		}

		lastIndex = i;
		indexBak = i;
		indexCnt++;
		if( pIdxBuf[i].offset != 0)
		{
		    offset = pIdxBuf[i].offset + pIdxBuf[i].frameLen;
		}
		if(0 != pIdxBuf[i].tmMS )
		{
			m_endTime = pIdxBuf[i].tmMS;
		}
	}

	ConvertTimeStr(m_endTime,tmpPath);
	if(0 == m_endTime)
	{
		m_endTime *= STFS_1SEC_MS;
	}

    if(indexCnt > 1)
	{
	    endOffset = pIdxBuf[indexBak - 1].offset + pIdxBuf[indexBak - 1].frameLen;
        m_endTime = (uint64_t)(pIdxBuf[indexBak - 1].tmMS);
	}

	endTime = m_endTime;
	if(pHead->endTime == pHead->startTime)
	{
		if(m_endTime > pHead->endTime)
		{
			pHead->endTime = m_endTime;
		}
	}

	if(i == 0 && startOffset == 0 )
	{
		startOffset = m_fileHead.dataOffset;
	}

	pDataBuf  = new uchar_t[bufSize+secSize];
    endOffset = offset;

    if(0 == offset)
    {
        offset = STFS_REC_DATA_OFFSET;
    }

	TRACE("Start read frame data. offset %d last index %d. Sector Size %d \n",offset,lastIndex,secSize);

	int ioSize	   = 0;
	int dataOffset = 0;
	int alignByte  = 0;
	int alignOffset= 0;
	int newIndex   = lastIndex; //此索引建立错误会导致I的数据与上一帧的偏移相等。
	int nCreateNum = 0;

	//读取开始时间
	if(0 == pHead->startTime)
	{
		ret = m_pFile->ReadPos(pHead->dataOffset,pDataBuf,SIZE_4KB);
		if(ret < 0)
		{
			TRACE("Read first frame  fail.ret %d.\n",ret);
		}
		else
		{
			m_frmTool.Init(pDataBuf);
			if(m_frmTool.IsEffect())
			{
				pHead->startTime = m_frmTool.GetFrameTime();
			}
			else
			{   //首个I帧的时间
				pHead->startTime = pIdxBuf[0].tmMS;
			}
		}
	}

	while((offset + FRM_HEAD_LEN) < recFileSize)
	{
		ioSize = ((offset + bufSize) < recSize)? bufSize: recSize - offset;
		TRACE_CBS("ReadPos offset %d  ioSize %d \n",alignOffset,ioSize);
		ret = m_pFile->ReadPos(offset,pDataBuf,ioSize);
		if(ret < 0)
		{
			TRACE_ERR("Read index buf fail. offset %d ioSize %d ret %d  \n",offset,ioSize,ret);
			goto CHECK_END;
		}
        TRACE_CBS("ReadPos %d  End ret %d   \n",offset,ret);
		dataOffset = 0;
		while((dataOffset+FRM_HEAD_LEN) < ioSize)
		{
			m_frmTool.Init(pDataBuf + dataOffset);

			if(!m_frmTool.IsEffect()) //检查
			{
				//检查结束
				TRACE("Check end .Current offset %d startOffset %d\n",offset,startOffset);
				ret = ERR_DATA_OVER_FILE;
				goto CHECK_END;
			}
			int64_t frmTime =  m_frmTool.GetFrameTime();
			uint32_t dataLen = m_frmTool.GetFrameLen();
			int  frmType = m_frmTool.GetFrameType();
			//时间小于开始时间，不属于当前录像段数据
            if(m_frmTool.GetFrameTime() < startTime ||
				m_frmTool.GetFrameTime() < pHead->startTime)
            {
                TRACE("End time %lld start time %lld \n",endTime,pHead->startTime);
                PrintTimeMs(frmTime,0,"cur frame time");
                PrintTimeMs(endTime,0,"end frame time");
                PrintTimeMs(pHead->startTime,0,"Start time");

                goto CHECK_END;
            }

            if(dataLen > STFS_GETFRM_BUFSIZE )
            {
                TRACE_ERR("Data len error %d \n",dataLen);
				ret = ERR_DATA_SIZE;
				goto CHECK_END;
            }

			//同时也要支持MJ视频帧
			if( m_frmTool.IsKeyFrame())
			{
				bool bCreate = true;
				//由于MJ每一帧都可以算是关键帧，可以单独解码出来
				if( 0 != nCreateNum)
				{
					plastIdx = & (pIdxBuf[newIndex - 1]);
				}

				if( nCreateNum != 0 &&
					ABS(frmTime -(int64_t) plastIdx->tmMS)< STFS_CREATE_IDX_MS)
				{
					bCreate = false;
				}

				if( bCreate &&
					pIdxBuf[newIndex].magic != STFS_REC_IDX_SIG )
				{
					//确保视频帧时间是一直往前增长的
					if(nCreateNum != 0)
					{
						if((offset + dataOffset) < (plastIdx->offset + plastIdx->frameLen))
						{
							TRACE("offset %d dataoffset %d frmoffset %d framelend %d.\n",
								   offset,dataOffset,plastIdx->offset,plastIdx->frameLen);
					//		 CROSS_ASSERT((offset + dataOffset) >= plastIdx->offset + plastIdx->frameLen);
							 goto CHECK_END;
						}
					}

					if(newIndex < (int)(maxNum -1))
					{
						uint32_t frameLen = 0;

						pIdxBuf[newIndex].NO        = newIndex;
						pIdxBuf[newIndex].offset    = offset + dataOffset;
						pIdxBuf[newIndex].frameType = m_frmTool.GetFrameType();
						CreateRecIdxSize(frameLen,dataLen,FRM_HEAD_LEN);
						pIdxBuf[newIndex].frameLen = frameLen;
						pIdxBuf[newIndex].tmMS      = (uint32_t)(frmTime/STFS_1SEC_MS);
						pIdxBuf[newIndex].magic      = STFS_REC_IDX_SIG;
						TRACE("Frame type %c newIndex %d  len  %d \n",frmType,newIndex,pIdxBuf[newIndex].frameLen);
						PrintTimeMs(frmTime,0,"IFrame index time");
						nCreateNum++;
						newIndex++;
					}
				}
			}

			dataOffset +=  dataLen;
			endOffset = offset + dataOffset;
			if(frmTime > endTime)
			{
				if((frmTime - endTime) < STFS_1DAY_MS)
				{
					endTime = frmTime;
				}
			}

		}
		offset += dataOffset;
	}

CHECK_END:
	TRACE("CH%02d Start Write index data create index %d .\n",pHead->channel,nCreateNum);
	//写入索引数据
	if(nCreateNum > 0)
	{
		uint32_t  sOffset  = STFS_REC_IDX_OFFSET  + lastIndex * REC_INDEX_LEN;
		uint32_t  eOffset  = STFS_REC_IDX_OFFSET  + newIndex * REC_INDEX_LEN;

		alignOffset = SIZE_ROUND_ALIGN(sOffset,secSize);
		alignByte   = sOffset - alignOffset;

		pBuf  =  ((uchar_t*)pIdxBuf);
		pBuf  =  pBuf + (alignOffset- STFS_REC_IDX_OFFSET);

		dataOffset  = SIZE_ROUND_UP(eOffset,secSize);
		ioSize = dataOffset - alignOffset;

		ret = m_pFile->WritePos(alignOffset,(uchar_t*)pBuf,ioSize);
		if(ret < 0)
		{
			TRACE("Write index buf fail.\n");
			//goto ERR_OUT;
		}
		TRACE("create new index data. new Index num %d start index %d\n",nCreateNum,lastIndex);
	}

	if(endOffset > startOffset)
	{
		fileSize = endOffset - startOffset;
	}
	else
	{
		TRACE("Error offset %d start offset %d .\n",endOffset,startOffset);
	}

	//头信息记录
	m_fileHead.endTime = pHead->endTime	   = endTime;
	m_fileHead.fileLen = pHead->fileLen	   = endOffset;
	m_fileHead.idxNum  = pHead->idxNum     = indexCnt;
	pHead->writeStatus = STFS_REC_END_FLAG;

	//文件段信息记录
	uint32_t segIndex = (uint32_t)m_vecSeg.size();
	if(segIndex < STFS_MAX_SEG_NUM)
 	{
 		pReg[segIndex].segNO       = segIndex;
 		pReg[segIndex].dataLen     = fileSize;
 		pReg[segIndex].data_start  = startOffset ;
 		pReg[segIndex].data_endpos = endOffset ;
 		pReg[segIndex].tmStart	   = startTime ;
 		pReg[segIndex].tmEnd	   = endTime ;
 		pReg[segIndex].magic       = STFS_REC_SEG_SIG;
 	}

	ret = m_pFile->WritePos(0,m_frmIdx.GetBufAddr(),STFS_REC_IDX_OFFSET);
	if(ret < 0)
	{
		TRACE("Write head info fail.ret %d \n",ret);
		goto ERR_OUT;
	}
	TRACE("CH %02d fileLBA %lld fileSize %d.\n",pHead->channel,fileLBA,fileSize);

	if(pDataBuf)
	{
		delete [] pDataBuf;
	}

	if(pIdxBuf)
	{
		delete [] pIdxBuf;
	}
	return 0;

ERR_OUT:
	if(pDataBuf)
	{
		delete [] pDataBuf;
	}
	if(pIdxBuf)
	{
		delete [] pIdxBuf;
	}
	TRACE("Repair file %lld fail.ret %d \n",fileLBA,ret);
	return ret;
}

int CRecordWriter::ClearFile(char*  diskName,uint32_t fileIndex,uint32_t fileSize,int64_t startTime,int64_t endTime)
{
	int ret = 0;
#if 0
	SerialFileRaw recFile;

	unsigned char* cleanBuf = new unsigned char[STFS_REC_DATA_OFFSET];

	memset(cleanBuf,0,STFS_REC_DATA_OFFSET);
	ret = recFile.Open(diskName,fileIndex,fileSize,SCSI_RDWR);
	if(ret < 0)
	{
		goto ERR_OUT;
	}

	ret = recFile.WritePos(0,cleanBuf,STFS_REC_DATA_OFFSET);
	if(ret < 0)
	{
		goto ERR_OUT;
	}

ERR_OUT:
	recFile.Close();
	delete [] cleanBuf;
#endif
	return ret;
}

bool CRecordWriter::IsContextCreateIdx(int frmType, int64_t time)
{
	//非I帧和MFrame帧, 不建立索引
	if(frmType != IFrame &&
	   frmType != MFrame)
	{
		return false;
	}

//使用偏移来建立索引
	if( m_recIdx.NO >= 2)
	{   //解决索引空间用完，但是文件还剩余还很多的情况
		uint32_t frmDiff = m_curPos - m_recIdx.offset;
		if(frmDiff <  m_idxDiffComSize)
		{
			return false;
		}
	}
	return  true;
}

void CRecordWriter::CreateRecIdxSize(uint32_t & idxLen,int frameSize,int fsHdLen)
{
	if(frameSize & 0x01)
	{
		idxLen = frameSize + fsHdLen + 1;
	}
	else
	{
		idxLen = frameSize + fsHdLen;
	}
}

int CRecordWriter::SaveSpsPps(uchar_t * data_buf, uint32_t data_size)
{
	return 0;
}
